"""
数据标准化处理模块
"""

import numpy as np
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler


def create_sample_data():
    """
    创建模拟的原始数据示例
    模拟真实场景中的不同量纲特征

    Returns:
        tuple: (X_raw, y) 特征矩阵和目标变量
    """
    np.random.seed(42)

    # 模拟不同量纲的特征
    # 年龄：20-80岁
    age = np.random.randint(20, 81, 100)
    # BMI：15-40 kg/m²
    bmi = np.random.uniform(15, 40, 100)
    # 血压：80-180 mmHg
    blood_pressure = np.random.randint(80, 181, 100)
    # 血糖：70-200 mg/dL
    blood_sugar = np.random.randint(70, 201, 100)

    # 创建特征矩阵
    X_raw = np.column_stack([age, bmi, blood_pressure, blood_sugar])

    # 创建目标变量（模拟糖尿病进展）
    y = (
        age * 0.5
        + bmi * 2
        + blood_pressure * 0.3
        + blood_sugar * 0.1
        + np.random.normal(0, 10, 100)
    )

    return X_raw, y


def standardize_zscore(X_train, X_test=None):
    """
    Z-score标准化函数
    将数据标准化为均值为0，标准差为1的分布

    Args:
        X_train: 训练集数据
        X_test: 测试集数据（可选）

    Returns:
        如果提供X_test: 返回 (X_train_scaled, X_test_scaled, scaler)
        如果不提供X_test: 返回 (X_train_scaled, scaler)
    """
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)

    if X_test is not None:
        X_test_scaled = scaler.transform(X_test)
        return X_train_scaled, X_test_scaled, scaler
    else:
        return X_train_scaled, scaler


def standardize_minmax(X_train, X_test=None, feature_range=(0, 1)):
    """
    MinMax标准化函数
    将数据缩放到指定范围（默认0-1）

    Args:
        X_train: 训练集数据
        X_test: 测试集数据（可选）
        feature_range: 缩放范围，默认为(0, 1)

    Returns:
        如果提供X_test: 返回 (X_train_scaled, X_test_scaled, scaler)
        如果不提供X_test: 返回 (X_train_scaled, scaler)
    """
    scaler = MinMaxScaler(feature_range=feature_range)
    X_train_scaled = scaler.fit_transform(X_train)

    if X_test is not None:
        X_test_scaled = scaler.transform(X_test)
        return X_train_scaled, X_test_scaled, scaler
    else:
        return X_train_scaled, scaler


def standardize_robust(X_train, X_test=None):
    """
    鲁棒标准化函数
    对异常值不敏感的标准化方法

    Args:
        X_train: 训练集数据
        X_test: 测试集数据（可选）

    Returns:
        如果提供X_test: 返回 (X_train_scaled, X_test_scaled, scaler)
        如果不提供X_test: 返回 (X_train_scaled, scaler)
    """
    scaler = RobustScaler()
    X_train_scaled = scaler.fit_transform(X_train)

    if X_test is not None:
        X_test_scaled = scaler.transform(X_test)
        return X_train_scaled, X_test_scaled, scaler
    else:
        return X_train_scaled, scaler


def get_scaler_info(scaler):
    """
    获取标准化器的参数信息

    Args:
        scaler: 标准化器实例

    Returns:
        dict: 标准化器参数信息
    """
    if isinstance(scaler, StandardScaler):
        return {"type": "StandardScaler", "mean": scaler.mean_, "std": scaler.scale_}
    elif isinstance(scaler, MinMaxScaler):
        return {
            "type": "MinMaxScaler",
            "data_min": scaler.data_min_,
            "data_max": scaler.data_max_,
            "feature_range": scaler.feature_range,
        }
    elif isinstance(scaler, RobustScaler):
        return {
            "type": "RobustScaler",
            "center": scaler.center_,
            "scale": scaler.scale_,
        }
    else:
        return {"type": "Unknown", "status": "无法识别标准化器类型"}


if __name__ == "__main__":
    # 1. 获取原始数据
    X, y = create_sample_data()
    X_train = X

    # 2. 使用Z-score标准化
    X_train_scaled, scaler = standardize_zscore(X_train)

    # 3. 获取参数信息
    info = get_scaler_info(scaler)

    # 4. 逆变换
    X_original = scaler.inverse_transform(X_train_scaled)
